﻿using NetTopologySuite.Geometries;
using NetTopologySuite.Index.Strtree;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace MassiveRender
{
    public class MassiveGraphicsRenderer
    {
        // 核心组件
        private readonly WriteableBitmap _finalBitmap;
        private readonly STRtree<GraphicLayer> _spatialIndex;
        private readonly Dictionary<Guid, GraphicLayer> _layers = new();
        private readonly Queue<Rect> _dirtyRegions = new();
        private readonly object _syncLock = new();

        // 渲染状态
        private bool _isRendering;
        private readonly DispatcherTimer _renderTimer;

        public WriteableBitmap FinalBitmap => _finalBitmap;

        public MassiveGraphicsRenderer(int width, int height, double dpi = 96)
        {
            // 初始化最终位图
            _finalBitmap = new WriteableBitmap(
                width, height, dpi, dpi, PixelFormats.Pbgra32, null);

            // 创建空间索引（使用第三方库 NetTopologySuite）
            _spatialIndex = new STRtree<GraphicLayer>();

            // 设置渲染定时器（60 FPS）
            _renderTimer = new DispatcherTimer(DispatcherPriority.Render);
            _renderTimer.Interval = TimeSpan.FromMilliseconds(16);
            _renderTimer.Tick += RenderDirtyRegions;
            _renderTimer.Start();
        }

        public Guid AddGraphic(IDrawable graphic)
        {
            var layer = new GraphicLayer(graphic);
            var id = Guid.NewGuid();

            lock (_syncLock)
            {
                _layers.Add(id, layer);

                // 添加到空间索引
                var env = new Envelope(
                    graphic.Bounds.Left, graphic.Bounds.Right,
                    graphic.Bounds.Top, graphic.Bounds.Bottom);
                _spatialIndex.Insert(env, layer);

                // 标记脏区域
                _dirtyRegions.Enqueue(graphic.Bounds);
            }

            return id;
        }

        public void UpdateGraphic(Guid id)
        {
            lock (_syncLock)
            {
                if (_layers.TryGetValue(id, out var layer))
                {
                    // 从索引中移除旧位置
                    var oldEnv = new Envelope(
                        layer.Graphic.Bounds.Left, layer.Graphic.Bounds.Right,
                        layer.Graphic.Bounds.Top, layer.Graphic.Bounds.Bottom);
                    _spatialIndex.Remove(oldEnv, layer);

                    // 更新图形
                    layer.IsDirty = true;

                    // 重新加入索引
                    var newEnv = new Envelope(
                        layer.Graphic.Bounds.Left, layer.Graphic.Bounds.Right,
                        layer.Graphic.Bounds.Top, layer.Graphic.Bounds.Bottom);
                    _spatialIndex.Insert(newEnv, layer);

                    // 标记脏区域（新旧区域）
                    _dirtyRegions.Enqueue(oldEnv.ToRect());
                    _dirtyRegions.Enqueue(layer.Graphic.Bounds);
                }
            }
        }

        public void RemoveGraphic(Guid id)
        {
            lock (_syncLock)
            {
                if (_layers.TryGetValue(id, out var layer))
                {
                    // 记录要移除的区域
                    var bounds = layer.Graphic.Bounds;

                    // 从索引中移除
                    var env = new Envelope(
                        bounds.Left, bounds.Right,
                        bounds.Top, bounds.Bottom);
                    _spatialIndex.Remove(env, layer);

                    // 从图层中移除
                    _layers.Remove(id);

                    // 标记脏区域
                    _dirtyRegions.Enqueue(bounds);
                }
            }
        }

        private void RenderDirtyRegions(object sender, EventArgs e)
        {
            if (_isRendering || _dirtyRegions.Count == 0) return;

            _isRendering = true;

            try
            {
                // 合并所有脏区域
                Rect totalDirty = Rect.Empty;
                while (_dirtyRegions.Count > 0)
                {
                    var rect = _dirtyRegions.Dequeue();
                    totalDirty = totalDirty.IsEmpty ? rect : Rect.Union(totalDirty, rect);
                }

                // 获取受影响的所有图形
                var env = new Envelope(
                    totalDirty.Left, totalDirty.Right,
                    totalDirty.Top, totalDirty.Bottom);

                var affectedLayers = _spatialIndex.Query(env)
                    .Cast<GraphicLayer>()
                    .Where(l => l.IsDirty || l.Bounds.IntersectsWith(totalDirty))
                    .OrderBy(l => l.ZIndex)
                    .ToList();

                // 创建离屏渲染目标
                var rtb = new RenderTargetBitmap(
                    (int)totalDirty.Width, (int)totalDirty.Height,
                    96, 96, PixelFormats.Pbgra32);

                var dv = new DrawingVisual();
                using (var dc = dv.RenderOpen())
                {
                    // 清除背景
                    dc.DrawRectangle(Brushes.Transparent, null, totalDirty);

                    // 渲染所有受影响图层
                    foreach (var layer in affectedLayers)
                    {
                        layer.Graphic.Draw(dc);
                        layer.IsDirty = false;
                    }
                }

                rtb.Render(dv);

                // 更新最终位图
                _finalBitmap.Lock();
                try
                {
                    var sourceRect = new Int32Rect(0, 0, (int)totalDirty.Width, (int)totalDirty.Height);
                    var pixels = new byte[(int)totalDirty.Width * (int)totalDirty.Height * 4];
                    rtb.CopyPixels(sourceRect, pixels, (int)totalDirty.Width * 4, 0);

                    _finalBitmap.WritePixels(
                        new Int32Rect((int)totalDirty.X, (int)totalDirty.Y,
                                     (int)totalDirty.Width, (int)totalDirty.Height),
                        pixels, (int)totalDirty.Width * 4, 0);
                }
                finally
                {
                    _finalBitmap.Unlock();
                }
            }
            finally
            {
                _isRendering = false;
            }
        }
    }

    // ===== 支持接口和类 =====
    public interface IDrawable
    {
        Rect Bounds { get; }
        void Draw(DrawingContext dc);
    }

    public class GraphicLayer
    {
        public IDrawable Graphic { get; }
        public bool IsDirty { get; set; } = true;
        public int ZIndex { get; set; }
        public Rect Bounds => Graphic.Bounds;

        public GraphicLayer(IDrawable graphic)
        {
            Graphic = graphic;
        }
    }

    // ===== 空间索引扩展 =====
    public static class EnvelopeExtensions
    {
        public static Rect ToRect(this Envelope env)
        {
            return new Rect(env.MinX, env.MinY, env.Width, env.Height);
        }
    }
}
